package com.zenithmind.document.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 端点配置管理器
 * 遵循开闭原则：对扩展开放，对修改关闭
 * 遵循单一职责原则：专注于端点配置管理
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Component
public class EndpointConfigurationManager {

    private final Map<String, List<String>> endpointCategories = new HashMap<>();
    
    public EndpointConfigurationManager() {
        initializeDefaultEndpoints();
    }

    /**
     * 初始化默认端点配置
     */
    private void initializeDefaultEndpoints() {
        // API文档端点
        addEndpointCategory("api-docs", Arrays.asList(
            "/v3/api-docs/**",
            "/swagger-ui/**",
            "/swagger-ui.html",
            "/doc.html",
            "/webjars/**",
            "/favicon.ico",
            "/knife4j/**",
            "/knife4j-ui/**",
            "/knife4j.html"
        ));

        // 公开访问端点
        addEndpointCategory("public", Arrays.asList(
            "/api/v1/documents/public/**",
            "/api/v1/documents/search",
            "/api/v1/documents/hot",
            "/api/v1/documents/latest",
            "/api/v1/documents/recommended",
            "/api/v1/documents/*/preview",
            "/api/v1/documents/*/download",
            "/api/v1/document-categories/public/**",
            "/api/v1/document-categories/tree",
            "/api/v1/documents/statistics/public",
            "/actuator/**",
            "/health",
            "/info"
        ));

        // 用户角色端点
        addEndpointCategory("user", Arrays.asList(
            "/api/v1/documents/**",
            "/api/v1/document-categories/**"
        ));

        // 作者角色端点
        addEndpointCategory("author", Arrays.asList(
            "/api/v1/documents/upload",
            "/api/v1/documents/create",
            "/api/v1/documents/*/edit",
            "/api/v1/documents/*/delete",
            "/api/v1/documents/*/convert",
            "/api/v1/documents/*/versions"
        ));

        // 管理员角色端点
        addEndpointCategory("admin", Arrays.asList(
            "/api/v1/documents/admin/**",
            "/api/v1/document-categories/admin/**",
            "/api/v1/documents/batch",
            "/api/v1/documents/move",
            "/api/v1/manage/**"
        ));
    }

    /**
     * 添加端点分类
     * 遵循开闭原则：允许添加新的端点分类而不修改现有代码
     */
    public void addEndpointCategory(String category, List<String> endpoints) {
        endpointCategories.put(category, new ArrayList<>(endpoints));
        log.info("添加端点分类: {} - {} 个端点", category, endpoints.size());
    }

    /**
     * 添加端点到指定分类
     */
    public void addEndpointToCategory(String category, String endpoint) {
        endpointCategories.computeIfAbsent(category, k -> new ArrayList<>()).add(endpoint);
        log.info("添加端点到分类 {}: {}", category, endpoint);
    }

    /**
     * 移除端点分类
     */
    public void removeEndpointCategory(String category) {
        endpointCategories.remove(category);
        log.info("移除端点分类: {}", category);
    }

    /**
     * 获取指定分类的端点
     */
    public String[] getEndpointsByCategory(String category) {
        List<String> endpoints = endpointCategories.get(category);
        return endpoints != null ? endpoints.toArray(new String[0]) : new String[0];
    }

    /**
     * 获取所有公开端点（API文档 + 公开访问）
     */
    public String[] getAllPublicEndpoints() {
        List<String> allPublic = new ArrayList<>();
        allPublic.addAll(endpointCategories.getOrDefault("api-docs", Collections.emptyList()));
        allPublic.addAll(endpointCategories.getOrDefault("public", Collections.emptyList()));
        return allPublic.toArray(new String[0]);
    }

    /**
     * 获取所有端点分类
     */
    public Set<String> getAllCategories() {
        return endpointCategories.keySet();
    }

    /**
     * 检查端点是否在指定分类中
     */
    public boolean isEndpointInCategory(String endpoint, String category) {
        List<String> endpoints = endpointCategories.get(category);
        if (endpoints == null) {
            return false;
        }
        
        return endpoints.stream().anyMatch(pattern -> 
            endpoint.matches(pattern.replace("**", ".*").replace("*", "[^/]*")));
    }

    /**
     * 验证端点配置
     */
    public boolean validateConfiguration() {
        log.info("验证端点配置");
        
        boolean isValid = true;
        
        // 检查是否有空的分类
        for (Map.Entry<String, List<String>> entry : endpointCategories.entrySet()) {
            if (entry.getValue().isEmpty()) {
                log.warn("端点分类 {} 为空", entry.getKey());
                isValid = false;
            }
        }
        
        // 检查是否有重复的端点
        Set<String> allEndpoints = new HashSet<>();
        for (List<String> endpoints : endpointCategories.values()) {
            for (String endpoint : endpoints) {
                if (!allEndpoints.add(endpoint)) {
                    log.warn("发现重复的端点配置: {}", endpoint);
                    isValid = false;
                }
            }
        }
        
        if (isValid) {
            log.info("端点配置验证通过，总分类数: {}, 总端点数: {}", 
                endpointCategories.size(), allEndpoints.size());
        } else {
            log.warn("端点配置验证失败");
        }
        
        return isValid;
    }
}
